package com.zengjin.service;

import com.google.common.base.CaseFormat;
import com.zengjin.config.ColumnClass;
import com.zengjin.config.TableClass;
import com.zengjin.test.common.R;
import com.zengjin.utils.DBUtils;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;


/**
 * @author 19324
 */
@Service
public class GenerateCodeService {

    Configuration cfg = null;

    {
        cfg = new Configuration(Configuration.VERSION_2_3_30);
        cfg.setTemplateLoader(new ClassTemplateLoader(GenerateCodeService.class, "/templates"));
        cfg.setDefaultEncoding("UTF-8");
    }

    public R generateCode(List<TableClass> tableClassList, String realPath) {
        try {
            //生成common类
            Template rTemplate = cfg.getTemplate("R.java.ftl");
            Template queryTemplate = cfg.getTemplate("Query.java.ftl");
            Template pageResponseTemplate = cfg.getTemplate("PageResponse.java.ftl");
            Template pageRequestTemplate = cfg.getTemplate("PageRequest.java.ftl");
            Template superUtilTemplate = cfg.getTemplate("SuperUtil.java.ftl");

            //生成config类
            Template jacksonConfigTemplate = cfg.getTemplate("JacksonConfig.java.ftl");
            Template myBatisPlusConfigTemplate = cfg.getTemplate("MyBatisPlusConfig.java.ftl");
            Template corsTemplate = cfg.getTemplate("CorsConfig.java.ftl");

            //生成Exception类
            Template globalExceptionHandlerTemplate = cfg.getTemplate("GlobalExceptionHandler.java.ftl");
            Template customExceptionTemplate = cfg.getTemplate("CustomException.java.ftl");


            //生成前端
            Template apiTemplate = cfg.getTemplate("API.ts.ftl");



            //生成实体类
            Template enTemplate = cfg.getTemplate("En.java.ftl");
            Template voTemplate = cfg.getTemplate("Vo.java.ftl");
            Template dtoTemplate = cfg.getTemplate("Dto.java.ftl");
            Template mapperJavaTemplate = cfg.getTemplate("Mapper.java.ftl");
            Template mapperXmlTemplate = cfg.getTemplate("Mapper.xml.ftl");
            Template serviceTemplate = cfg.getTemplate("Service.java.ftl");
            Template serviceImplTemplate = cfg.getTemplate("ServiceImpl.java.ftl");
            Template controllerTemplate = cfg.getTemplate("Controller.java.ftl");
            Connection connection = DBUtils.getConnection();
            DatabaseMetaData metaData = connection.getMetaData();
            boolean isConfig = false;//是否生成配置类
            for (TableClass tableClass : tableClassList) {
                ResultSet columns = metaData.getColumns(connection.getCatalog(), null, tableClass.getTableName(), null);
                ResultSet primaryKeys = metaData.getPrimaryKeys(connection.getCatalog(), null, tableClass.getTableName());
                List<ColumnClass> columnClassList = new ArrayList<>();
                while (columns.next()) {
                    String column_name = columns.getString("COLUMN_NAME");
                    String type_name = columns.getString("TYPE_NAME");
                    String remarks = columns.getString("REMARKS");
                    ColumnClass columnClass = new ColumnClass();
                    columnClass.setRemark(remarks);
                    columnClass.setColumnName(column_name);
                    columnClass.setType(type_name);
                    columnClass.setPropertyName(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, column_name));
                    while (primaryKeys.next()) {
                        String pkName = primaryKeys.getString("COLUMN_NAME");
                        if (column_name.equals(pkName)) {
                            columnClass.setPrimary(true);
                        }
                    }
                    columnClassList.add(columnClass);
                }
                tableClass.setColumns(columnClassList);
                tableClass.setVos(tableClass.getVos());
                String path = realPath + "/" + tableClass.getPackageName().replace(".", "/");
                if (!isConfig) {
                    //生成common类
                    generate(rTemplate, tableClass, path + "/common/");
                    generate(queryTemplate, tableClass, path + "/common/");
                    generate(pageResponseTemplate, tableClass, path + "/common/");
                    generate(pageRequestTemplate, tableClass, path + "/common/");
                    generate(superUtilTemplate, tableClass, path + "/common/");

                    //生成config类
                    generate(jacksonConfigTemplate, tableClass, path + "/config/");
                    generate(myBatisPlusConfigTemplate, tableClass, path + "/config/");
                    generate(corsTemplate, tableClass, path + "/config/");

                    //生成Exception类
                    generate(globalExceptionHandlerTemplate, tableClass, path + "/exception/");
                    generate(customExceptionTemplate, tableClass, path + "/exception/");

                    //生成前端
                    generate(apiTemplate, tableClass, path + "/api/");

                    isConfig = true;
                }

                generate(enTemplate, tableClass, path + "/model/en/");
                generate(voTemplate, tableClass, path + "/model/vo/");
                generate(dtoTemplate, tableClass, path + "/model/dto/");
                generate(mapperJavaTemplate, tableClass, path + "/mapper/");
                generate(mapperXmlTemplate, tableClass, path + "/mapper/xml/");
                generate(serviceTemplate, tableClass, path + "/service/");
                generate(serviceImplTemplate, tableClass, path + "/service/impl");
                generate(controllerTemplate, tableClass, path + "/controller/");
            }
            return R.success("代码已生成", realPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return R.error("代码生成失败");
    }

    private void generate(Template template, TableClass tableClass, String path) throws IOException, TemplateException {
        File folder = new File(path);
        if (!folder.exists()) {
            folder.mkdirs();
        }
        String fileName = "";
        //判断是配置类，就不换名称
        List<String> configList = new ArrayList<>();
        configList.add("JacksonConfig.java.ftl");
        configList.add("MyBatisPlusConfig.java.ftl");
        configList.add("CorsConfig.java.ftl");
        configList.add("R.java.ftl");
        configList.add("Query.java.ftl");
        configList.add("PageRequest.java.ftl");
        configList.add("PageResponse.java.ftl");
        configList.add("GlobalExceptionHandler.java.ftl");
        configList.add("CustomException.java.ftl");
        configList.add("SuperUtil.java.ftl");
        configList.add("Api.java.ftl");

        if (configList.contains(template.getName())) {
            fileName = path + "/" + template.getName().replace(".ftl", "");
        } else {
            fileName = path + "/" + tableClass.getEnName() + template.getName().replace(".ftl", "").replace("En", "");
        }
        FileOutputStream fos = new FileOutputStream(fileName);
        OutputStreamWriter out = new OutputStreamWriter(fos);
        template.process(tableClass, out);
        fos.close();
        out.close();
    }


}
